package com.vt.admin.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimap;
import com.vt.admin.api.dto.CityTreeNode;
import com.vt.admin.api.dto.CityTreeNodeOld;
import com.vt.admin.api.dto.DictDto;
import com.vt.admin.api.dto.TreeNode;
import com.vt.admin.api.entity.SysDictionary;
import com.vt.admin.api.vo.TreeUtil;
import com.vt.admin.mapper.SysDictMapper;
import com.vt.common.core.constant.CommonConstant;
import com.vt.common.core.util.R;
import lombok.AllArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.boot.CommandLineRunner;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@AllArgsConstructor
public class SysDictService implements CommandLineRunner {

    SysDictMapper mapper;
    StringRedisTemplate redisTemplate;

    public IPage<SysDictionary> list(long page, long size, SysDictionary t) {
        return mapper.selectPage(new Page(page, size), new QueryWrapper(t));
    }

    public R findOne(String id) {
        return new R(mapper.selectById(id));
    }

    public R save(SysDictionary t) {
        if (StringUtils.isNotEmpty(t.getId())) {
            return new R(mapper.updateById(t));
        } else {
            return new R(mapper.insert(t));
        }
    }

    public R delete(String id) {
        return new R(mapper.deleteById(id));
    }


    public R<ListMultimap<String, DictDto>> findSimpleAll() {
        ListMultimap<String, Map> multimap = ArrayListMultimap.create();

        List<SysDictionary> all = mapper.selectList(new QueryWrapper<>());
        for (SysDictionary sysDict : all) {
            multimap.put(sysDict.getType(),
                    Dict.create().set(sysDict.getValue(), sysDict.getText()));
        }
        return new R(multimap.asMap());
    }

    @Async
    public void writeRedis() {
        List<SysDictionary> list = mapper.selectList(new LambdaQueryWrapper());
        redisTemplate.opsForValue().set(CommonConstant.REDIS_DICT_PREFIX, JSONUtil.toJsonStr(list));
    }

    @Override
    public void run(String... args) {
        writeRedis();
    }

    private List<SysDictionary> getList() {
        return JSONUtil.toList(
                JSONUtil.parseArray(redisTemplate.opsForValue().get(CommonConstant.REDIS_DICT_PREFIX)),
                SysDictionary.class);
    }

    public List<SysDictionary.Simple> findByType(String type) {
        List<SysDictionary> list = getList();
        List<SysDictionary.Simple> rs = new ArrayList();

        for (SysDictionary dict : list) {
            if (StrUtil.equals(type, dict.getType()))
                rs.add(dict.simpleMap());
        }

        CollUtil.sortByProperty(rs, "sort");
        return rs;
    }

    public R<List<TreeNode>> cityTreeNode() {
        List<CityTreeNode> list = mapper.getCityTreeList();
        return new R(TreeUtil.buildByRecursiveParent(list, "0"));
    }


    /**
     * 兼容一期的城市控件
     *
     * @return
     */
    public List<CityTreeNodeOld> cityTree() {
        List<CityTreeNodeOld> list = mapper.getAllProvince();
        List<CityTreeNodeOld.CityNode> cityList = mapper.getAllCity();
        Multimap<String, CityTreeNodeOld.CityNode> multimap = ArrayListMultimap.create();

        for (CityTreeNodeOld.CityNode city : cityList) {
            multimap.put(city.getProvinceId(), city);
        }

        for (CityTreeNodeOld node : list) {
            if (multimap.containsKey(node.getPId())) {
                node.getChildren().addAll(multimap.get(node.getPId()));
            }
        }
        return list;
    }
}
